﻿using System.Collections.Generic;
using System.Diagnostics.Contracts;
using Castle.Windsor;

namespace Pipeline.Middleware.Contractual
{
    public interface IApplicationBuilder
    {
        IWindsorContainer Container { get; }

        void Use(IMiddleware middleware);

        void UseArrange(List<IMiddleware> middlewares);

        Context Run(Context context);
    }

    public class ApplicationBuilder : IApplicationBuilder
    {
        public IWindsorContainer Container { get; private set; }
        private readonly List<IMiddleware> _middlewares;

        public ApplicationBuilder(IWindsorContainer container)
        {
            Contract.Requires(container!=null,"container!=null");

            _middlewares=new List<IMiddleware>();
            Container = container;
        }

        public void Use(IMiddleware middleware)
        {
            Contract.Requires(middleware != null, "middleware!=null");

            _middlewares.Add(middleware);
        }

        public void UseArrange(List<IMiddleware> middlewares)
        {
            Contract.Requires(middlewares != null, "middlewares!=null");

            _middlewares.AddRange(middlewares);
        }

        public Context Run(Context context)
        {
            Contract.Requires(context!=null,"context!=null");

            var request=context.Request;
            var response=context.Response;

            foreach (var middleware in _middlewares)
            {
                request = middleware.ProcessRequest(request);
            }

            _middlewares.Reverse();

            foreach (var middleware in _middlewares)
            {
                response = middleware.ProcessResponse(response);
            }

            return new Context(request,response);
        }
    }
}